﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_LOCAL_POOL_H__
#define __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_LOCAL_POOL_H__

#include "fake_lock.h"
#include "xos_list.h"

namespace xos_stl
{

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // local_pool

	template< class T, class PoolLock = fake_lock, class ListLock = fake_lock >
    class local_pool
    {
    public:
		typedef PoolLock POOL_LOCK;
		typedef ListLock LIST_LOCK;
		typedef xos_list< T, LIST_LOCK > LIST;
		typedef typename LIST::const_iterator CONST_ITER;
		typedef typename LIST::iterator ITER;

    protected:
		size_t _xos_stl_local_pool_total_num;
		POOL_LOCK _xos_stl_local_pool_lock;
        typename T::POOL * _xos_stl_local_pool_pool_ptr;
        LIST _xos_stl_local_pool_list;

    protected:
        void init_list( LIST & list, int nNum )
		{
			for( int i = 0; i < nNum; ++i )
			{
				T * p = _xos_stl_local_pool_pool_ptr->GetItemLock();
				list.push_back( p );
				_xos_stl_local_pool_total_num++;
			}
		}
        void term_list( LIST & list )
		{
			for( ITER i = list.begin(); i != list.end(); ++i )
			{
				T * pTemp = *i;
				_xos_stl_local_pool_pool_ptr->put_item( pTemp, true );
				_xos_stl_local_pool_total_num--;
			}
			list.clear();
		}
    public:
        local_pool( typename T::POOL * pPool, int nNum )
		{
			_xos_stl_local_pool_pool_ptr = pPool;
			_xos_stl_local_pool_total_num = 0;
			init_list( _xos_stl_local_pool_list, nNum );
		}
        local_pool( typename T::POOL * pPool )
		{
			_xos_stl_local_pool_pool_ptr = pPool;
			_xos_stl_local_pool_total_num = 0;
		}
        local_pool()
		{
			_xos_stl_local_pool_pool_ptr = 0;
			_xos_stl_local_pool_total_num = 0;
		}
        ~local_pool()
		{
			term_list( _xos_stl_local_pool_list );
		}
        void init_local_pool( typename T::POOL * pPool, int nNum )
		{
			_xos_stl_local_pool_pool_ptr = pPool;
			_xos_stl_local_pool_total_num = 0;
			init_list( _xos_stl_local_pool_list, nNum );
		}
        void release_all( bool bLock )
		{
			if( bLock )
			{
				lock();
			}
			term_list( _xos_stl_local_pool_list );
			if( bLock )
			{
				un_lock();
			}
		}
        T * get_item_from_pool( bool bLock )
		{
			T * pItem = 0;
			if( bLock )
			{
				lock();
			}
			if( _xos_stl_local_pool_list.size() > 0 )
			{
				pItem = _xos_stl_local_pool_list.front();
				_xos_stl_local_pool_list.pop_front();
			}
			else
			{
				pItem = _xos_stl_local_pool_pool_ptr->GetItem();
				_xos_stl_local_pool_total_num++;
			}
			if( bLock )
			{
				un_lock();
			}
			return pItem;
		}
        void put_back_to_pool( T * pT, bool bLock )
		{
			if( bLock )
			{
				lock();
			}
			_xos_stl_local_pool_list.push_back( pT );
			if( bLock )
			{
				un_lock();
			}
		}
		size_t get_total_count( bool bLock )
		{
			size_t num = 0;
			if( bLock )
			{
				lock();
			}
			num = _xos_stl_local_pool_total_num;
			if( bLock )
			{
				un_lock();
			}
			return num;
		}
		size_t get_count( bool bLock )
		{
			size_t num = 0;
			if( bLock )
			{
				lock();
			}
			num = _xos_stl_local_pool_list.size();
			if( bLock )
			{
				un_lock();
			}
			return num;
		}
		void un_lock()
		{
			_xos_stl_local_pool_lock.un_lock();
		}
		void lock()
		{
			_xos_stl_local_pool_lock.lock();
		}
    };

} // xos_stl

#endif // __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_LOCAL_POOL_H__
